﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UX_GL_FRAME_BUFFER_OBJECT_H
#define _UX_GL_FRAME_BUFFER_OBJECT_H

#include "GLStateManager.h"
#include "GLObjectManager.h"
#include "GLTexture.h"
#include "GLRenderBuffer.h"

namespace UX_STL
{
namespace GLShell
{

	//
	// Frame Buffer Object
	//

	class UX_EXPORT GLFrameBuffer : public GLBaseObject
	{
	public:
		struct GLFrameBufferInfo
		{
			enum EType
			{
				R	= 0,
				G,
				B,
				A,
				DEPTH,
				STENCIL,
				_SIZE,
			};
			typedef static_array< uint, _SIZE >						comsize_array_t;
			typedef static_array< gl_tex_component::type, _SIZE >	comptype_array_t;

			comsize_array_t			aCompSize;			// size in bits of RGBA color, depth, stencil components
			gl_tex_component::type	eCompType;			// type of RGBA color, depth, stencil components
			gl_color_encoding::type	eColorEncoding;
			gl_fbo_attach::type		eAttachment;
			gl_fbo_object::type		eObjType;
			///
			GLFrameBufferInfo():
				eCompType(gl_tex_component::NONE), eColorEncoding(gl_color_encoding::NONE),
				eAttachment(gl_fbo_attach::NONE), eObjType(gl_fbo_object::NONE) {}
		};

		typedef array< GLFrameBufferInfo >	fb_info_array_t;

	private:
		enum {
			_DEPTH			= 0,
			_DEPTH_STENCIL,
			_STENCIL,
			_COLOR_OFFSET,
			_BUFFER_SIZE	= _COLOR_OFFSET + UX_GL_MAX_DRAW_BUFFERS,
		};

		struct TBuffer
		{
			GLuint					uID;
			gl_texture::type		eTarget;
			gl_fbo_attach::type		eAttach;
			///
			TBuffer(GLuint id = 0, gl_texture::type target = gl_texture::_UNKNOWN,
					gl_fbo_attach::type attach = gl_fbo_attach::NONE):
					uID(id), eTarget(target), eAttach(attach) {}
		};

		typedef static_array< TBuffer, _BUFFER_SIZE >				buffers_t;
		typedef static_array< gl_fbo_attach::type, _BUFFER_SIZE >	drawbuffers_t;

	private:
		buffers_t			_aBuffers;			// Depth + Stencil + Colors buffers
		drawbuffers_t		_aDrawBuffers;
		GLuint				_uID;

	private:
		static uint					_s_AttachmentToIndex(gl_fbo_attach::type eAttach);
		static gl_fbo_attach::type	_s_IndexToAttachment(usize idx);

		void _Attach2D(const GLTexture &pTex, gl_fbo_attach::type eAttach, uint uLevel);
		void _AttachLayer(const GLTexture &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel);

	public:
		GLFrameBuffer();
		GLFrameBuffer(GLFrameBuffer &);
		~GLFrameBuffer();

		bool  Create();
		void  Destroy();
		bool  CheckStatus();
		
		void  Bind()	 const;
		void  Unbind()	 const;
		bool  IsBinded() const;
		void  ApplyDrawBuffers() const;
		
		void  Attach(const GLTexture &pTex, gl_fbo_attach::type eAttach, uint uLevel = 0);	// attach all layers and faces of texture
		void  Attach2D(const GLTexture2D &pTex, gl_fbo_attach::type eAttach, uint uLevel = 0);
		void  Attach2D(const GLTexture2DMS &pTex, gl_fbo_attach::type eAttach, uint uLevel = 0);
		void  Attach3D(const GLTexture3D &pTex, gl_fbo_attach::type eAttach, uint uDepth = 0, uint uLevel = 0);
		void  AttachLayer(const GLTexture2DArray &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel = 0);
		void  AttachLayer(const GLTexture3D &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel = 0);
		void  AttachLayer(const GLTexture2DMSArray &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel = 0);
		void  AttachLayer(const GLTextureCubeArray &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel = 0);
		void  AttachFace(const GLTextureCube &pTex, gl_fbo_attach::type eAttach, gl_cube_face::type eFace, uint uLevel = 0);
		void  AttachFace(const GLTextureCubeArray &pTex, gl_fbo_attach::type eAttach, gl_cube_face::type eFace, uint uLayer, uint uLevel = 0);
		void  Attach(const GLRenderBuffer &pRB, gl_fbo_attach::type eAttach);	// render buffer

		void  Detach(gl_fbo_attach::type eAttach);
		void  DetachAll();

		// for color buffer only
		bool  Enable(gl_fbo_attach::type eAttach);	
		bool  Disable(gl_fbo_attach::type eAttach);
		bool  IsEnabled(gl_fbo_attach::type eAttach) const;
		void  DisableAll();
		void  UpdateBuffers();

		bool  Blit(const GLFrameBuffer &pFBO, const irect &sRead, const irect &sWrite, gl_attrib_mask::type eMask, gl_fbo_blit::type eFilter) const;

		void  ClearColor(const fvec4  &vFColor = fvec4(0.f)) const;
		void  ClearColor(const ivec4 &vIColor = ivec4(0)) const;
		void  ClearColor(const uvec4 &vUColor = uvec4(0)) const;
		void  ClearDepth(float fDepth = 1.f)	const;
		void  ClearStencil(int iStencil = 0)	const;
		void  ClearDepthStencil(float fDepth = 1.f, int iStencil = 0) const;
		void  ClearAll() const;

		bool  GetAttachmentInfo(GLFrameBufferInfo &sInfo, gl_fbo_attach::type eAttach) const;
		bool  GetEnabledAttachmentInfo(fb_info_array_t &aInfo) const;
		bool  GetAllAttachmentInfo(fb_info_array_t &aInfo) const;

		GLuint	Id()						const	{ return _uID; }
		GLuint	GetDepthBuffer()			const	{ return _aBuffers[0].uID; }
		GLuint	GetStencilBuffer()			const	{ return _aBuffers[1].uID; }
		GLuint	GetColorBuffer(uint i)		const	{ return _aBuffers[i+_COLOR_OFFSET].uID; }
		GLenum	Target()					const	{ return GL_DRAW_FRAMEBUFFER; }

		
		static bool s_CheckFrameBufferFunctions();
	};



	//
	// Default Frame Buffer
	//

	class UX_EXPORT GLDefaultFrameBuffer : public GLBaseObject
	{
	public:
		typedef GLFrameBuffer::GLFrameBufferInfo	GLFrameBufferInfo;
		typedef GLFrameBuffer::fb_info_array_t		fb_info_array_t;

	public:
		static void BindDraw(gl_draw_buffer::type eBuffer);
		static void BindRead(gl_read_buffer::type eBuffer);

		static void ClampColor(bool bClamp);
		static bool Read(const ivec2 &vOffset, const uvec2 &vDim, gl_pixel_format::type eFormat, gl_pixel::type eType, void *pData);
		static bool GetImageDataSize(const uvec2 &vDim, gl_pixel_format::type eFormat, gl_pixel::type eType, usize &uDataSize);
		static bool GetBufferInfo(GLFrameBufferInfo &sInfo, gl_system_buffer::type eBuffer);
		static bool GetAllBuffersInfo(fb_info_array_t &aInfo);

		static gl_draw_buffer::type	DrawBuffer();
		static gl_read_buffer::type	ReadBuffer();
		
		static void ClearBuffers(bool bColor = true, bool bDepth = false, bool bStencil = false);
		static void ClearColor(const fvec4  &vFColor = fvec4(0.f), uint uBuffer = 0);
		static void ClearColor(const ivec4 &vIColor = ivec4(0), uint uBuffer = 0);
		static void ClearColor(const uvec4 &vUColor = uvec4(0), uint uBuffer = 0);
		static void ClearDepth(float fDepth = 1.f);
		static void ClearStencil(int iStencil = 0);
		static void ClearDepthStencil(float fDepth = 1.f, int iStencil = 0);
		
		static void SetClearColor(const color4f &vColor);
		static void SetClearDepth(float fDepth);
		static void SetClearStencil(int iStencil);
	};

	

	
	
//-------------------------- GLFrameBuffer ------------------------//
/*
=================================================
	устанавливает кадровый буфер текущим
=================================================
*/
	inline void GLFrameBuffer::Bind() const
	{
		SMAN()->BindDrawFramebuffer( _uID );
	}

/*
=================================================
	возвращает стандартный буфер
=================================================
*/
	inline void GLFrameBuffer::Unbind() const
	{
		ASSERT( IsBinded() );
		SMAN()->BindFramebuffer( 0 );
	}
	
/*
=================================================
	явлеется ли этот кдровый буфер текущим
=================================================
*/
	inline bool GLFrameBuffer::IsBinded() const
	{
		return SMAN()->GetDrawFBO() == _uID;
	}
	
/*
=================================================
	устанавливает кадровый буфер текущим
=================================================
*/
	inline void GLFrameBuffer::ApplyDrawBuffers() const
	{
		GL_CALL( glDrawBuffers( (GLsizei)_aDrawBuffers.Count() - _COLOR_OFFSET, (GLenum *)_aDrawBuffers.ptr() + _COLOR_OFFSET ) );
	}

/*
=================================================
	меняет режим буферов
=================================================
*/
	inline void GLFrameBuffer::UpdateBuffers()
	{
		for (usize i = _COLOR_OFFSET; i < _aBuffers.Count(); ++i)
		{
			if ( _aBuffers[i].uID != 0 )
				_aDrawBuffers[i] = gl_fbo_attach::COLOR_0 + i - _COLOR_OFFSET;
			else
				_aDrawBuffers[i] = gl_fbo_attach::NONE;
		}
	}
	
/*
=================================================
	очищает используемые буферы цвета,
	буфер глубины и накопления
=================================================
*/
	inline void GLFrameBuffer::ClearColor(const fvec4 &vFColor) const
	{
		ASSERT( IsBinded() );

		for (GLint i = _COLOR_OFFSET; i < (GLint)_aDrawBuffers.Count(); ++i)
		{
			if ( _aDrawBuffers[i] != gl_fbo_attach::NONE )
				GL_CALL( glClearBufferfv( GL_COLOR, i - _COLOR_OFFSET, vFColor.ptr() ) );
		}
	}

	inline void GLFrameBuffer::ClearColor(const ivec4 &vIColor) const
	{
		ASSERT( IsBinded() );

		for (GLint i = _COLOR_OFFSET; i < (GLint)_aDrawBuffers.Count(); ++i)
		{
			if ( _aDrawBuffers[i] != gl_fbo_attach::NONE )
				GL_CALL( glClearBufferiv( GL_COLOR, i - _COLOR_OFFSET, vIColor.ptr() ) );
		}
	}

	inline void GLFrameBuffer::ClearColor(const uvec4 &vUColor) const
	{
		ASSERT( IsBinded() );

		for (GLint i = _COLOR_OFFSET; i < (GLint)_aDrawBuffers.Count(); ++i)
		{
			if ( _aDrawBuffers[i] != gl_fbo_attach::NONE )
				GL_CALL( glClearBufferuiv( GL_COLOR, i - _COLOR_OFFSET, vUColor.ptr() ) );
		}
	}
	
	inline void GLFrameBuffer::ClearDepth(float fDepth) const
	{
		ASSERT( IsBinded() );
		GL_CALL( glClearBufferfv( GL_DEPTH, 0, &fDepth ) );
	}

	inline void GLFrameBuffer::ClearStencil(int iStencil) const
	{
		ASSERT( IsBinded() );
		GL_CALL( glClearBufferiv( GL_STENCIL, 0, &iStencil ) );
	}
	
	inline void GLFrameBuffer::ClearDepthStencil(float fDepth, int iStencil) const
	{
		ASSERT( IsBinded() );
		GL_CALL( glClearBufferfi( GL_DEPTH_STENCIL, 0, fDepth, iStencil ) );
	}

/*
=================================================
	очищает все активные присоединенные цели рендера
=================================================
*/
	inline void GLFrameBuffer::ClearAll() const
	{
		ASSERT( IsBinded() );
		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
	}

/*
=================================================
	возвращает индекс в буфере целей рендеринга
=================================================
*/
	inline uint GLFrameBuffer::_s_AttachmentToIndex(gl_fbo_attach::type eAttach)
	{
		if ( eAttach >= gl_fbo_attach::COLOR_0 and
			 eAttach <= gl_fbo_attach::COLOR_15 )		return eAttach - gl_fbo_attach::COLOR_0 + _COLOR_OFFSET;
		if ( eAttach == gl_fbo_attach::DEPTH )			return _DEPTH;
		if ( eAttach == gl_fbo_attach::DEPTH_STENCIL )	return _DEPTH_STENCIL;
		if ( eAttach == gl_fbo_attach::STENCIL )		return _STENCIL;

		WARNING( "Unknown attachment" );
		return -1;
	}

/*
=================================================
	возвращает константу по которой присоединяется
	цель рендеринга
=================================================
*/
	inline gl_fbo_attach::type GLFrameBuffer::_s_IndexToAttachment(usize idx)
	{
		ASSERT( idx != usize(-1) and "Incorrect index" );

		if ( idx >= _COLOR_OFFSET )		return gl_fbo_attach::COLOR_0 + idx - _COLOR_OFFSET;
		if ( idx == _DEPTH )			return gl_fbo_attach::DEPTH;
		if ( idx == _DEPTH_STENCIL )	return gl_fbo_attach::DEPTH_STENCIL;
		if ( idx == _STENCIL )			return gl_fbo_attach::STENCIL;

		WARNING( "Unknwon attachment index" );
		return (gl_fbo_attach::type)-1;
	}

/*
=================================================
	присоединяет текстуру или ее слой
=================================================
*/
	inline void GLFrameBuffer::Attach(const GLTexture &pTex, gl_fbo_attach::type eAttach, uint uLevel)
	{
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= pTex.Id();
		_aBuffers[idx].eTarget	= pTex.Target();
		_aDrawBuffers[idx]		= eAttach;
		GL_CALL( glNamedFramebufferTexture( _uID, eAttach, pTex.Id(), uLevel ) );
	}

/*
=================================================
	присоединяет 2Д текстуру
=================================================
*/
	inline void GLFrameBuffer::_Attach2D(const GLTexture &pTex, gl_fbo_attach::type eAttach, uint uLevel)
	{
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= pTex.Id();
		_aBuffers[idx].eTarget	= pTex.Target();
		_aDrawBuffers[idx]		= eAttach;
		GL_CALL( glNamedFramebufferTexture2D( _uID, eAttach, pTex.Target(), pTex.Id(), uLevel ) );
	}
	
	inline void GLFrameBuffer::Attach2D(const GLTexture2D &pTex, gl_fbo_attach::type eAttach, uint uLevel) {
		return _Attach2D( pTex, eAttach, uLevel );
	}

	inline void GLFrameBuffer::Attach2D(const GLTexture2DMS &pTex, gl_fbo_attach::type eAttach, uint uLevel) {
		return _Attach2D( pTex, eAttach, uLevel );
	}
	
/*
=================================================
	присоединяет 3Д текстуру
=================================================
*/
	inline void GLFrameBuffer::Attach3D(const GLTexture3D &pTex, gl_fbo_attach::type eAttach, uint uDepth, uint uLevel)
	{
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= pTex.Id();
		_aBuffers[idx].eTarget	= pTex.Target();
		_aDrawBuffers[idx]		= eAttach;
		GL_CALL( glNamedFramebufferTexture3D( _uID, eAttach, pTex.Target(), pTex.Id(), uLevel, uDepth ) );
	}
	
/*
=================================================
	присоединяет слой текстуры
=================================================
*/
	inline void GLFrameBuffer::_AttachLayer(const GLTexture &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel)
	{
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= pTex.Id();
		_aBuffers[idx].eTarget	= pTex.Target();
		_aDrawBuffers[idx]		= eAttach;
		GL_CALL( glNamedFramebufferTextureLayer( _uID, eAttach, pTex.Id(), uLevel, uLayer ) );
	}

	inline void GLFrameBuffer::AttachLayer(const GLTexture3D &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel) {
		return _AttachLayer( pTex, eAttach, uLayer, uLevel );
	}

	inline void GLFrameBuffer::AttachLayer(const GLTexture2DArray &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel) {
		return _AttachLayer( pTex, eAttach, uLayer, uLevel );
	}

	inline void GLFrameBuffer::AttachLayer(const GLTexture2DMSArray &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel) {
		return _AttachLayer( pTex, eAttach, uLayer, uLevel );
	}

	inline void GLFrameBuffer::AttachLayer(const GLTextureCubeArray &pTex, gl_fbo_attach::type eAttach, uint uLayer, uint uLevel) {
		return _AttachLayer( pTex, eAttach, uLayer, uLevel );
	}

/*
=================================================
	присоединяет грань кубической текстуры
=================================================
*/
	inline void GLFrameBuffer::AttachFace(const GLTextureCube &pTex, gl_fbo_attach::type eAttach, gl_cube_face::type eFace, uint uLevel)
	{
		ASSERT( eFace >= gl_cube_face::_FIRST and eFace <= gl_cube_face::_LAST );
		
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= pTex.Id();
		_aBuffers[idx].eTarget	= (gl_texture::type)eFace;
		_aDrawBuffers[idx]		= eAttach;
		GL_CALL( glNamedFramebufferTexture2D( _uID, eAttach, eFace, pTex.Id(), uLevel ) );
		//GL_CALL( glNamedFramebufferTextureFace( _uID, eAttach, pTex->Id(), uLevel, eFace ) );
	}

/*
=================================================
	присоединяет грань из массива кубических текстур
=================================================
*/
	inline void GLFrameBuffer::AttachFace(const GLTextureCubeArray &pTex, gl_fbo_attach::type eAttach, gl_cube_face::type eFace, uint uLayer, uint uLevel)
	{
		ASSERT( eFace >= gl_cube_face::_FIRST and eFace <= gl_cube_face::_LAST );
		
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= pTex.Id();
		_aBuffers[idx].eTarget	= (gl_texture::type)eFace;
		_aDrawBuffers[idx]		= eAttach;
		GL_CALL( glNamedFramebufferTextureLayer( _uID, eAttach, pTex.Id(), uLevel, uLayer*6 + eFace - gl_cube_face::_FIRST ) );
	}
	
/*
=================================================
	присоединяет рендер буфер
=================================================
*/
	inline void GLFrameBuffer::Attach(const GLRenderBuffer &pRB, gl_fbo_attach::type eAttach)
	{
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= pRB.Id();
		_aBuffers[idx].eTarget	= (gl_texture::type)pRB.Target();
		_aDrawBuffers[idx]		= eAttach;
		GL_CALL( glNamedFramebufferRenderbuffer( _uID, eAttach, pRB.Target(), pRB.Id() ) );
	}
	
/*
=================================================
	удаляет текстуру из ФБО
=================================================
*/
	inline void GLFrameBuffer::Detach(gl_fbo_attach::type eAttach)
	{
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		_aBuffers[idx].uID		= 0;
		_aBuffers[idx].eTarget	= gl_texture::_UNKNOWN;
		_aDrawBuffers[idx]		= gl_fbo_attach::NONE;
		GL_CALL( glNamedFramebufferTexture2D( _uID, eAttach, gl_texture::TEXTURE_2D, 0, 0 ) );
	}
	
/*
=================================================
	включает текстуру или рендер буфер
=================================================
*/
	inline bool GLFrameBuffer::Enable(gl_fbo_attach::type eAttach)
	{
		const usize	idx	= _s_AttachmentToIndex( eAttach );

		if ( eAttach < gl_fbo_attach::COLOR_0 or _aBuffers[idx].uID == 0 )
			return false;

		_aDrawBuffers[idx] = eAttach;
		return true;
	}

/*
=================================================
	отключает текстуру или рендер буфер
=================================================
*/
	inline bool GLFrameBuffer::Disable(gl_fbo_attach::type eAttach)
	{
		const usize	idx	= _s_AttachmentToIndex( eAttach );

		//if ( eAttach < gl_fbo_attach::COLOR_0 or _aBuffers[idx].uID != 0 )
		//	return false;

		_aDrawBuffers[idx] = gl_fbo_attach::NONE;
		return true;
	}
	
/*
=================================================
	отключает все текстуры и рендер буферы
=================================================
*/
	inline void GLFrameBuffer::DisableAll()
	{
		FORv( i, _COLOR_OFFSET, _aDrawBuffers ) {
			_aDrawBuffers[i] = gl_fbo_attach::NONE;
		}
	}
	
/*
=================================================
	возвращает TRUE если присоединена текстура
	или рендер буфер, а рендеринг в них отключен
=================================================
*/
	inline bool GLFrameBuffer::IsEnabled(gl_fbo_attach::type eAttach) const
	{
		const usize	idx			= _s_AttachmentToIndex( eAttach );
		
		if ( eAttach < gl_fbo_attach::COLOR_0 or _aBuffers[idx].uID != 0 )
			return false;

		return ( _aDrawBuffers[idx] == gl_fbo_attach::NONE and _aBuffers[idx].uID != 0 );
	}



	
//----------------------- GLDefaultFrameBuffer --------------------//
/*
=================================================
	устанавливает системный буфер цвета для рисования
=================================================
*/
	inline void GLDefaultFrameBuffer::BindDraw(gl_draw_buffer::type eBuffer)
	{
		GL_CALL( glDrawBuffer( eBuffer ) );
	}
	
/*
=================================================
	устанавливает системный буфер цвета для чтения
=================================================
*/
	inline void GLDefaultFrameBuffer::BindRead(gl_read_buffer::type eBuffer)
	{
		GL_CALL( glReadBuffer( eBuffer ) );
	}
	
/*
=================================================
	считывает пиксели из текущего read_buffer'а
=================================================
*/
	inline bool GLDefaultFrameBuffer::Read(const ivec2 &vOffset, const uvec2 &vDim, gl_pixel_format::type eFormat, gl_pixel::type eType, void *pData)
	{
		GL_CALL_R( glReadPixels( vOffset.x, vOffset.y, vDim.x, vDim.y, eFormat, eType, pData ) );
		return true;
	}
	
/*
=================================================
	возвращает текущий буфер рисования
=================================================
*/
	inline gl_draw_buffer::type GLDefaultFrameBuffer::DrawBuffer()
	{
		GLint	i_db = 0;
		GL_CALL( glGetIntegerv( GL_DRAW_BUFFER, &i_db ) );
		return (gl_draw_buffer::type)i_db;
	}
	
/*
=================================================
	возвращает текущий буфер чтения
=================================================
*/
	inline gl_read_buffer::type GLDefaultFrameBuffer::ReadBuffer()
	{
		GLint	i_rb = 0;
		GL_CALL( glGetIntegerv( GL_READ_BUFFER, &i_rb ) );
		return (gl_read_buffer::type)i_rb;
	}
	
/*
=================================================
	включает clamp цвета для операции glReadPixels
=================================================
*/
	inline void GLDefaultFrameBuffer::ClampColor(bool bClamp)
	{
		GL_CALL( glClampColor( GL_CLAMP_READ_COLOR, bClamp ) );
	}
	
/*
=================================================
	очищает буфер цвета, глубины и накопления
=================================================
*/
	inline void GLDefaultFrameBuffer::ClearColor(const fvec4 &vFColor, uint uBuffer)
	{
		GL_CALL( glClearBufferfv( GL_COLOR, uBuffer, vFColor.ptr() ) );
	}

	inline void GLDefaultFrameBuffer::ClearColor(const ivec4 &vIColor, uint uBuffer)
	{
		GL_CALL( glClearBufferiv( GL_COLOR, uBuffer, vIColor.ptr() ) );
	}

	inline void GLDefaultFrameBuffer::ClearColor(const uvec4 &vUColor, uint uBuffer)
	{
		GL_CALL( glClearBufferuiv( GL_COLOR, uBuffer, vUColor.ptr() ) );
	}

	inline void GLDefaultFrameBuffer::ClearDepth(float fDepth)
	{
		GL_CALL( glClearBufferfv( GL_DEPTH, 0, &fDepth ) );
	}

	inline void GLDefaultFrameBuffer::ClearStencil(int iStencil)
	{
		GL_CALL( glClearBufferiv( GL_STENCIL, 0, &iStencil ) );
	}
	
	inline void GLDefaultFrameBuffer::ClearDepthStencil(float fDepth, int iStencil)
	{
		GL_CALL( glClearBufferfi( GL_DEPTH_STENCIL, 0, fDepth, iStencil ) );
	}

/*
=================================================
	очищает все буферы
=================================================
*/
	inline void GLDefaultFrameBuffer::ClearBuffers(bool bColor, bool bDepth, bool bStencil)
	{
		GL_CALL( glClear(	(GL_COLOR_BUFFER_BIT * bColor) |
							(GL_DEPTH_BUFFER_BIT * bDepth) |
							(GL_STENCIL_BUFFER_BIT * bStencil)  ) );
	}
	
/*
=================================================
	устанавливает значения для очисти буферов
=================================================
*/
	inline void GLDefaultFrameBuffer::SetClearColor(const color4f &vColor)
	{
		GL_CALL( glClearColor( vColor.x, vColor.y, vColor.z, vColor.w ) );
	}

	inline void GLDefaultFrameBuffer::SetClearDepth(float fDepth)
	{
		GL_CALL( glClearDepthf( fDepth ) );
	}

	inline void GLDefaultFrameBuffer::SetClearStencil(int iStencil)
	{
		GL_CALL( glClearStencil( iStencil ) );
	}

//-------------------------------------------------------------------
	
}	// GLShell
}	// UX_STL

#endif	// _UX_GL_FRAME_BUFFER_OBJECT_H